/***************************************************************************
 *   Copyright (C) 2008 by Bartosz Dolewski  				   *
 *   E-mail: doles2@gmail.com   					   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "piq.h"

Piq::Piq(QWidget *parent, Qt::WFlags f) : QWidget(parent,f)
{
  ui.setupUi(this);

  QTextCodec::setCodecForTr (QTextCodec::codecForName ("UTF-8"));
  setWindowTitle("Piq");
  qDebug()<<"Program has started...\n";
  
  ui.publicIpProgressBar->reset();
  createNetworkList();
  createTrayIcon();
  createConnections();
 
}

void Piq::createNetworkList()
{
  //first of all we have to fill up our QList with interfaces which are found in this machine
  //just simple foreach macro will do a `la "for loop" to get interfaces

  qDebug()<<"Creating list of founded networks...\n";
  networkList = QNetworkInterface::allInterfaces ();

  foreach(QNetworkInterface NetInter, networkList)
  {
    if(NetInter.isValid())
    {
     ui.interfacesComboBox->addItem(NetInter.name());
    }
  }
 qDebug()<<"\t[+] NetworkList is done\n";
}

void Piq::createTrayIcon()
{
  qDebug()<<"Building tray icon....\n";	
  icon		   = QIcon (QString(":images/tray_icon.xpm"));
  trayIcon         = new QSystemTrayIcon;
  contextMenu      = new QMenu;
  showHideAction   = new QAction(tr("Show"), this);
  aboutApplication = new QAction(tr("About Application"),this);
  quitApplication  = new QAction(tr("Quit Application"),this);

  
  trayIcon->setIcon(icon);

  //adding actions to tray icon menu

  contextMenu->addAction(showHideAction);
  contextMenu->addSeparator();
  contextMenu->addAction(aboutApplication);
  contextMenu->addSeparator();
  contextMenu->addAction(quitApplication);
  contextMenu->setDefaultAction(showHideAction);
  qDebug()<<"\t[+] Tray icon has built\n";

  //when we fire up this application, main window will be visible
  //so this variable should be false

  isHidden = false;	
  showHideAction->setText( tr("Hide")); 
  
  trayIcon->setContextMenu(contextMenu);
  trayIcon->show();
}
void Piq::closeEvent(QCloseEvent *event)
 {
 //this function is a reimpletementation of closeEvent from QWidget.
 //We would like to not quit from program if the user will click the X button of our window :)
 //Just ignore this event, when X button is clicked, close the window not whole application
     if (trayIcon->isVisible())
     {
	hide();
        event->ignore();
	isHidden = true;
	showHideAction->setText( tr("Show"));
     }
 }

void Piq::createConnections()
{
  qDebug()<<"Building connections...\n";
  //connections from TrayIcon
  

  connect(showHideAction,   SIGNAL(triggered()), this, SLOT(showHide()));
  connect(quitApplication,  SIGNAL(triggered()), qApp, SLOT(quit()));
  connect(aboutApplication, SIGNAL(triggered()), this, SLOT(about())); 
  connect(trayIcon, 	    SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayIconClicked(QSystemTrayIcon::ActivationReason)));
  
  //connections from first tab

  connect(ui.ipPushButton, 	  SIGNAL(clicked()), 	  this, SLOT(showIP()));
  connect(ui.macPushButton, 	  SIGNAL(clicked()), 	  this, SLOT(showMAC()));
  connect(ui.broadcastPushButton, SIGNAL(clicked()),	  this, SLOT(showBroadcast()));
  connect(ui.netmaskPushButton,   SIGNAL(clicked()), 	  this, SLOT(showNetmask()));
  connect(ui.refreshPushButton,   SIGNAL(clicked()),	  this, SLOT(refreshEverything()));
  connect(ui.interfacesComboBox,  SIGNAL(activated(int)), this, SLOT(setInterface(int)));

  //connections from second tab

  createHttpConnection();
  connect(ui.publicIpPushButton ,  SIGNAL(clicked()),      	       this, SLOT(getPublicIP()));
  connect(http		        ,  SIGNAL(requestFinished(int, bool)), this, SLOT(showPublicIP(int, bool)));
  connect(http			,  SIGNAL(dataReadProgress(int, int)), this, SLOT(updateProgressBar(int,int)));
  qDebug()<<"\t[+] Connections have already created....\n";
}

void Piq::createHttpConnection()
{
  qDebug()<<"Creating http connection...\n";
  http = new QHttp(this);
  http->setHost("checkip.dyndns.org");
  ui.actionLabel->setText("nothing");
  qDebug()<<"\t[+] Http connection has created\n";
}

void Piq::getPublicIP()
{ 
  //I have to split up getting public IP into 2 functions.
  //First we create HTTP request and that`s all. We cannot show our public IP here because
  //it doesn`t exist at all. We should wait for requestFinished signal to display our data from host.
  //So it is much simplier to get data once and show it at second function call (of course it will be 2 slots)

  qDebug()<<"Getting public IP data...\n";
  httpGetId = http->get("/indeks.html");
  ui.actionLabel->setText("connecting...");

  //we should clear the progress bar
  ui.publicIpProgressBar->reset();
  qDebug()<<"\t[+] Done\n";
}

void Piq::showPublicIP(int reqID, bool errorCondition)
{
  //the http://checkip.dyndns.org/indeks.html returns message like a:
  //Current IP Address: 83.8.201.188 (with HTML tags)
  //We have to remove all character from start to ":" and from "</body>" to the end
  //later we will move bytes to QString and then display on lineEdit
  //PS: the reqID variable is useless here (yet), I`ve added it to compatibility with requestFinished signal
  //maybe in the future we will find some point to use reqID :)

  QByteArray byteBuffer;
  byteBuffer = http->readAll();
  
  //remove characters from beginning to semicolon

  int index = byteBuffer.indexOf(":");
  byteBuffer.remove(0,index+1);

  //and truncate bytes of buffer after IP string

  index = byteBuffer.indexOf(QString("</body>"));
  byteBuffer.truncate(index);

  if(errorCondition == false)
  {
   ui.publicIpLineEdit->setText(QString(byteBuffer.constData()));
   publicIp = ui.publicIpLineEdit->text();
   ui.actionLabel->setText("OK");
  }
  else
  {
   QMessageBox::critical(this, tr("Connection with host"),tr("It seems that some trouble happened during connection with host"));
   ui.actionLabel->setText("ERROR");
  }
}

void Piq::updateProgressBar(int howMuchDownloaded, int howMuchTotal)
{
  ui.actionLabel->setText(tr("Downloading"));
  
  //settting up the progressbar propeties
  ui.publicIpProgressBar->setMaximum(howMuchTotal);
  ui.publicIpProgressBar->setValue(howMuchDownloaded);
}
void Piq::showIP()
{
  qDebug()<<"showIP()...\n";

  //pieces of ToolTip code are ugly, that`s true :) We have to work at this

  trayIcon->setToolTip("IP: " + ip + "\n"  + tr("Public IP: ") + publicIp);
 if ( networkInterface.isValid() )
    {
        QList<QNetworkAddressEntry> entry = networkInterface.addressEntries();
        ip = entry.at(0).ip().toString();
    }
    else
    {
        ip = "unknown";
    }

 if (ui.ipLineEdit->text() != ip)
    {
	qDebug()<<"Setting IP adres to ipLineEdit...\n";
	ui.ipLineEdit->setText(ip);
	qDebug()<<"\t[+] Done\n";
    }
}
void Piq::showMAC()
{
 qDebug()<<"showMAC()...\n";
	if(networkInterface.isValid() )
	{
		mac = networkInterface.hardwareAddress();
	}
	else
	{
		mac = "unknown";
	}

	if (ui.macLineEdit->text() != mac)
	{
		qDebug()<<"Setting up hardware address...\n";
		ui.macLineEdit->setText(mac);
		qDebug()<<"\t[+] Done\n";
	}

}

void Piq::showBroadcast()
{
 qDebug()<<"showBroadcast...\n";
	if(networkInterface.isValid())
	{
		//broadcast = networkInterface.broadcast();
		 QList<QNetworkAddressEntry> entry = networkInterface.addressEntries();
        	 broadcast = entry.at(0).broadcast().toString();
	}
	else
	{
		broadcast = "unknown";
	}
	if(ui.broadcastLineEdit->text() != broadcast)
	{
		qDebug()<<"Setting up broadcast address...\n";
		ui.broadcastLineEdit->setText(broadcast);
		qDebug()<<"\t[+] Done\n";
	}
}
void Piq::showNetmask()
{
 qDebug()<<"showNetmask()...\n";
	if(networkInterface.isValid())
	{
		//netmask = networkInterface.netmask();
		 QList<QNetworkAddressEntry> entry = networkInterface.addressEntries();
        	 netmask = entry.at(0).netmask().toString();
	}
	else
	{
		netmask = "unknown";
	}
	if(ui.netmaskLineEdit->text() != netmask)
	{
		qDebug()<<"Setting up netmask address...\n";
		ui.netmaskLineEdit->setText(netmask);
		qDebug()<<"\t[+] Done\n";
	}
}

void Piq::refreshEverything()
{
	qDebug()<<"Refreshing all fields...\n";
	if(flags.testFlag(QNetworkInterface::IsUp))
	{
	 
	 emit showIP();
	 emit showMAC();
	 emit showBroadcast();
	 emit showNetmask();
	}
	else
	{
	 QMessageBox::warning(this ,tr("Interface not active"),tr("Interface which you have just chosen isn`t active."
								 " I can`t get information about it"));	
	ui.ipLineEdit->setText("...");
	ui.macLineEdit->setText("...");
	ui.netmaskLineEdit->setText("...");
	ui.broadcastLineEdit->setText("...");
	}
	qDebug()<<"\t[+] Done\n";
}

void Piq::showHide()
{
    if ( isHidden )
    {
        this->show();
        showHideAction->setText( tr("Hide"));
        isHidden = false;
    }

    else
    {
        this->hide();
        showHideAction->setText( tr("Show"));
        isHidden = true;
    }
}


void Piq::trayIconClicked( QSystemTrayIcon::ActivationReason reason )
{
    if ( reason == QSystemTrayIcon::Trigger )
    {
        emit showHide();
    }
}

void Piq::about()
{
 //If you changed anything in source code just add yourself here to this message box.
 //You are author of this program too :)

 QMessageBox::about(this ,tr("About Application"),tr("<b> Piq v 0.3 </b><br/>"
						    "------------------<br/>"
						    "Fast, small and smart utility to get you most important<br/>"
						    "Internet connection data. Piq is  a network-ace up Your sleeve.<br/><br/>"
						    "2008 by Bartosz Dolewski"));
}

void Piq::setInterface(int index)
{
 qDebug()<<"Setting up new interface...\n";
 networkInterface = networkList.at(index);

 //setting up the status of connection
 flags = networkInterface.flags();

 	if(flags.testFlag(QNetworkInterface::IsUp))
	   ui.currentStatusLabel->setText(tr("active"));
	else 
	   ui.currentStatusLabel->setText(tr("Non-active"));

 qDebug()<<"Network name: "<<networkInterface.name();
 qDebug()<<"\t[+] Done\n";
}
